#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2023/3/2 14:00
# @Author  : WuJunQi
# @Email   : 1479652129@qq.com
# @File    : yolov5_class.py
# @Software: PyCharm
import argparse
import os
import platform
import sys
import time
from pathlib import Path
from tkinter import Image

import numpy as np
import torch
# DeepSORT -> Importing DeepSORT.
from deep_sort.deep_sort.application_util import preprocessing
from deep_sort.deep_sort.deep_sort import nn_matching
from deep_sort.deep_sort.deep_sort.detection import Detection
from deep_sort.deep_sort.deep_sort.tracker import Tracker
from deep_sort.deep_sort.tools import generate_detections as gdet



from PyQt5.QtGui import QImage, QPixmap

from pyqt.People import Peoples

FILE = Path(__file__).resolve()
ROOT = FILE.parents[0]  # YOLOv5 root directory
if str(ROOT) not in sys.path:
    sys.path.append(str(ROOT))  # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd()))  # relative

from models.common import DetectMultiBackend
from utils.dataloaders import IMG_FORMATS, VID_FORMATS, LoadImages, LoadScreenshots, LoadStreams
from utils.general import (LOGGER, Profile, check_file, check_img_size, check_imshow, check_requirements, colorstr, cv2,
                           increment_path, non_max_suppression, print_args, scale_boxes, strip_optimizer, xyxy2xywh)
from utils.plots import Annotator, colors, save_one_box
from utils.torch_utils import select_device, smart_inference_mode




class yolov5():
    def __init__(self,source):
        self.source = source
    @staticmethod
    def run(
            queue,
            Widget,
            weights=ROOT / 'yolov5s.pt',  # model path or triton URL
            source=ROOT / 'data/images',  # file/dir/URL/glob/screen/0(webcam)
            data=ROOT / 'data/coco128.yaml',  # dataset.yaml path
            imgsz=(640, 520),  # inference size (height, width)
            conf_thres=0.25,  # confidence threshold
            iou_thres=0.45,  # NMS IOU threshold
            max_det=1000,  # maximum detections per image
            device='',  # cuda device, i.e. 0 or 0,1,2,3 or cpu
            view_img=False,  # show results
            save_txt=False,  # save results to *.txt
            save_conf=False,  # save confidences in --save-txt labels
            save_crop=False,  # save cropped prediction boxes
            nosave=False,  # do not save images/videos
            classes=None,  # filter by class: --class 0, or --class 0 2 3
            agnostic_nms=False,  # class-agnostic NMS
            augment=False,  # augmented inference
            visualize=False,  # visualize features
            update=False,  # update all models
            project=ROOT / 'runs/detect',  # save results to project/name
            name='exp',  # save results to project/name
            exist_ok=False,  # existing project/name ok, do not increment
            line_thickness=3,  # bounding box thickness (pixels)
            hide_labels=False,  # hide labels
            hide_conf=False,  # hide confidences
            half=False,  # use FP16 half-precision inference
            dnn=False,  # use OpenCV DNN for ONNX inference
            vid_stride=1,  # video frame-rate stride
    ):
        ################################################# 1. 初始化配置 #####################################################
        source = str(source)
        save_img = not nosave and not source.endswith('.txt')  # save inference images
        is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)
        is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))
        webcam = source.isnumeric() or source.endswith('.streams') or (is_url and not is_file)
        screenshot = source.lower().startswith('screen')
        if is_url and is_file:
            source = check_file(source)  # download

        # DeepSORT -> Initializing tracker.
        max_cosine_distance = 0.4
        nn_budget = None
        model_filename = './mars-small128.pb'
        encoder = gdet.create_box_encoder(model_filename, batch_size=1)
        metric = nn_matching.NearestNeighborDistanceMetric("cosine", max_cosine_distance, nn_budget)
        tracker = Tracker(metric)






        # Directories
        save_dir = increment_path(Path(project) / name, exist_ok=exist_ok)  # increment run
        (save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir

        # Load model
        device = select_device(device)
        model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
        stride, names, pt = model.stride, model.names, model.pt
        imgsz = check_img_size(imgsz, s=stride)  # check image size
        ################################################# 2. 加载数据 #####################################################
        # Dataloader 加载数据
        # 使用视频流或者页面
        # Dataloader
        bs = 1  # batch_size
        if webcam:
            view_img = check_imshow(warn=True)
            dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
            bs = len(dataset)
        elif screenshot:
            dataset = LoadScreenshots(source, img_size=imgsz, stride=stride, auto=pt)
        else:
            dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
        vid_path, vid_writer = [None] * bs, [None] * bs

        # Run inference
        model.warmup(imgsz=(1 if pt or model.triton else bs, 3, *imgsz))  # warmup
        seen, windows, dt = 0, [], (Profile(), Profile(), Profile())
        frame_idx = 0

        Widget.detectPeople.set_Zebra_crossing_edge(Widget.label.four_point[0].x(),Widget.label.four_point[0].y(),Widget.label.four_point[1].x(),Widget.label.four_point[1].y())
        for path, im, im0s, vid_cap, s in dataset:
            # mask for certain region
            # 1,2,3,4 分别对应左上，右上，右下，左下四个点
            hl1 = Widget.label.four_point[0].y() / Widget.label.pixmap().height() # 监测区域高度距离图片顶部比例
            wl1 = Widget.label.four_point[0].x() / Widget.label.pixmap().width()  # 监测区域高度距离图片左部比例
            hl2 = Widget.label.four_point[1].y() / Widget.label.pixmap().height()# 监测区域高度距离图片顶部比例
            wl2 = Widget.label.four_point[1].x() / Widget.label.pixmap().width()  # 监测区域高度距离图片左部比例
            hl3 = Widget.label.four_point[2].y() / Widget.label.pixmap().height()  # 监测区域高度距离图片顶部比例
            wl3 = Widget.label.four_point[2].x() / Widget.label.pixmap().width()  # 监测区域高度距离图片左部比例
            hl4 = Widget.label.four_point[3].y() / Widget.label.pixmap().height()  # 监测区域高度距离图片顶部比例
            wl4 = Widget.label.four_point[3].x() / Widget.label.pixmap().width()  # 监测区域高度距离图片左部比例
            if webcam:
                for b in range(0, im.shape[0]):
                    mask = np.zeros([im[b].shape[1], im[b].shape[2]], dtype=np.uint8)
                    # mask[round(img[b].shape[1] * hl1):img[b].shape[1], round(img[b].shape[2] * wl1):img[b].shape[2]] = 255
                    pts = np.array([[int(im[b].shape[2] * wl1), int(im[b].shape[1] * hl1)],  # pts1
                                    [int(im[b].shape[2] * wl2), int(im[b].shape[1] * hl2)],  # pts2
                                    [int(im[b].shape[2] * wl3), int(im[b].shape[1] * hl3)],  # pts3
                                    [int(im[b].shape[2] * wl4), int(im[b].shape[1] * hl4)]], np.int32)
                    mask = cv2.fillPoly(mask, [pts], (255, 255, 255))
                    imgc = im[b].transpose((1, 2, 0))
                    imgc = cv2.add(imgc, np.zeros(np.shape(imgc), dtype=np.uint8), mask=mask)
                    # cv2.imshow('1',imgc)
                    im[b] = imgc.transpose((2, 0, 1))

            else:
                mask = np.zeros([im.shape[1], im.shape[2]], dtype=np.uint8)
                # mask[round(img.shape[1] * hl1):img.shape[1], round(img.shape[2] * wl1):img.shape[2]] = 255
                pts = np.array([[int(im.shape[2] * wl1), int(im.shape[1] * hl1)],  # pts1
                                [int(im.shape[2] * wl2), int(im.shape[1] * hl2)],  # pts2
                                [int(im.shape[2] * wl3), int(im.shape[1] * hl3)],  # pts3
                                [int(im.shape[2] * wl4), int(im.shape[1] * hl4)]], np.int32)
                mask = cv2.fillPoly(mask, [pts], (255, 255, 255))
                im = im.transpose((1, 2, 0))
                im = cv2.add(im, np.zeros(np.shape(im), dtype=np.uint8), mask=mask)
                im = im.transpose((2, 0, 1))



            with dt[0]:
                im = torch.from_numpy(im).to(model.device)
                im = im.half() if model.fp16 else im.float()  # uint8 to fp16/32
                im /= 255  # 0 - 255 to 0.0 - 1.0
                if len(im.shape) == 3:
                    im = im[None]  # expand for batch dim

            # Inference
            with dt[1]:
                visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False
                pred = model(im, augment=augment, visualize=visualize)

            # NMS
                """
                pred: 网络的输出结果
                conf_thres:置信度阈值
                ou_thres:iou阈值
                classes: 是否只保留特定的类别
                agnostic_nms: 进行nms是否也去除不同类别之间的框
                max-det: 保留的最大检测框数量
                ---NMS, 预测框格式: xywh(中心点+长宽)-->xyxy(左上角右下角)
                pred是一个列表list[torch.tensor], 长度为batch_size
                每一个torch.tensor的shape为(num_boxes, 6), 内容为box + conf + cls
                """

            with dt[2]:
                pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)

            # Second-stage classifier (optional)
            # pred = utils.general.apply_classifier(pred, classifier_model, im, im0s)
            # 保存打印
            # Process predictions

                # Second-stage classifier (optional).
                # pred = utils.general.apply_classifier(pred, classifier_model, im, im0s)

            frame_idx = frame_idx + 1

            for i, det in enumerate(pred):  # per image
                seen += 1
                # if webcam:  # batch_size >= 1
                #     p, im0, frame = path[i], im0s[i].copy(), dataset.count
                #     s += f'{i}: '
                # else:
                #     p, im0, frame = path, im0s.copy(), getattr(dataset, 'frame', 0)
                if webcam:  # batch_size >= 1
                    p, s, im0, frame = path[i], f'{i}: ', im0s[i].copy(), dataset.count
                    cv2.putText(im0, "Detection_Region", (int(im0.shape[1] * wl1 - 5), int(im0.shape[0] * hl1 - 5)),
                                cv2.FONT_HERSHEY_SIMPLEX,
                                0.5, (255, 255, 0), 1, cv2.LINE_AA)

                    pts = np.array([[int(im0.shape[1] * wl1), int(im0.shape[0] * hl1)],  # pts1
                                    [int(im0.shape[1] * wl2), int(im0.shape[0] * hl2)],  # pts2
                                    [int(im0.shape[1] * wl3), int(im0.shape[0] * hl3)],  # pts3
                                    [int(im0.shape[1] * wl4), int(im0.shape[0] * hl4)]], np.int32)  # pts4
                    # pts = pts.reshape((-1, 1, 2))
                    zeros = np.zeros((im0.shape), dtype=np.uint8)
                    mask = cv2.fillPoly(zeros, [pts], color=(0, 165, 255))
                    im0 = cv2.addWeighted(im0, 1, mask, 0.2, 0)
                    cv2.polylines(im0, [pts], True, (255, 255, 0), 3)
                    # plot_one_box(dr, im0, label='Detection_Region', color=(0, 255, 0), line_thickness=2)
                else:
                    p, s, im0, frame = path, '', im0s.copy(), getattr(dataset, 'frame', 0)
                    cv2.putText(im0, "Detection_Region", (int(im0.shape[1] * wl1 - 5), int(im0.shape[0] * hl1 - 5)),
                                cv2.FONT_HERSHEY_SIMPLEX,
                                1.0, (255, 255, 0), 2, cv2.LINE_AA)
                    pts = np.array([[int(im0.shape[1] * wl1), int(im0.shape[0] * hl1)],  # pts1
                                    [int(im0.shape[1] * wl2), int(im0.shape[0] * hl2)],  # pts2
                                    [int(im0.shape[1] * wl3), int(im0.shape[0] * hl3)],  # pts3
                                    [int(im0.shape[1] * wl4), int(im0.shape[0] * hl4)]], np.int32)  # pts4
                    # pts = pts.reshape((-1, 1, 2))
                    zeros = np.zeros((im0.shape), dtype=np.uint8)
                    mask = cv2.fillPoly(zeros, [pts], color=(0, 165, 255))
                    im0 = cv2.addWeighted(im0, 1, mask, 0.2, 0)
                    cv2.polylines(im0, [pts], True, (255, 255, 0), 3)
                p = Path(p)  # to Path
                save_path = str(save_dir / p.name)  # im.jpg
                txt_path = str(save_dir / 'labels' / p.stem) + (
                    '' if dataset.mode == 'image' else f'_{frame}')  # im.txt
                s += '%gx%g ' % im.shape[2:]  # print string
                gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
                imc = im0.copy() if save_crop else im0  # for save_crop
                # 添加检测框
                annotator = Annotator(im0, line_width=line_thickness, example=str(names))
                if len(det):
                    # Rescale boxes from img_size to im0 size
                    det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round()

                    # Print results
                    for c in det[:, 5].unique():
                        n = (det[:, 5] == c).sum()  # detections per class
                        s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  # add to string
                    # DeepSORT -> Extracting Bounding boxes and its confidence scores.
                    bboxes = []
                    scores = []
                    for *boxes, conf, cls in det:
                        bbox_left = min([boxes[0].item(), boxes[2].item()])
                        bbox_top = min([boxes[1].item(), boxes[3].item()])
                        bbox_w = abs(boxes[0].item() - boxes[2].item())
                        bbox_h = abs(boxes[1].item() - boxes[3].item())
                        box = [bbox_left, bbox_top, bbox_w, bbox_h]
                        bboxes.append(box)
                        scores.append(conf.item())

                    # DeepSORT -> Getting appearance features of the object.
                    features = encoder(im0, bboxes)
                    # DeepSORT -> Storing all the required info in a list.
                    detections = [Detection(bbox, score, feature) for bbox, score, feature in
                                  zip(bboxes, scores, features)]

                    # DeepSORT -> Predicting Tracks.
                    tracker.predict()
                    tracker.update(detections)
                    # track_time = time.time() - prev_time

                    # DeepSORT -> Plotting the tracks.
                    for track in tracker.tracks:
                        if not track.is_confirmed() or track.time_since_update > 1:
                            continue

                        # DeepSORT -> Changing track bbox to top left, bottom right coordinates.
                        bbox = list(track.to_tlbr())

                        # DeepSORT -> Writing Track bounding box and ID on the frame using OpenCV.
                        txt = 'id:' + str(track.track_id)
                        (label_width, label_height), baseline = cv2.getTextSize(txt, cv2.FONT_HERSHEY_SIMPLEX, 1, 1)
                        top_left = tuple(map(int, [int(bbox[0]), int(bbox[1]) - (label_height + baseline)]))
                        top_right = tuple(map(int, [int(bbox[0]) + label_width, int(bbox[1])]))
                        org = tuple(map(int, [int(bbox[0]), int(bbox[1]) - baseline]))

                        # cv2.rectangle(im0, (int(bbox[0]), int(bbox[1])), (int(bbox[2]), int(bbox[3])), (255, 0, 0),
                        #               1)
                        # cv2.rectangle(im0, top_left, top_right, (255, 0, 0), -1)
                        save_format = '{frame},{id},{x1},{y1},{w},{h},{x},{y},{z}\n'
                        line = save_format.format(frame=frame_idx, id=track.track_id, x1=int(bbox[0]),
                                                  y1=int(bbox[1]), w=int(bbox[2] - bbox[0]),
                                                  h=int(bbox[3] - bbox[1]), x=-1, y=-1, z=-1)
                        Widget.detectPeople.addnew(track.track_id,int((bbox[2] - bbox[0])/2),int((bbox[3] - bbox[1])/2))
                        if Widget.detectPeople.count_crossnum(track.track_id):
                            txt = txt + "want"
                        else:
                            txt = txt + "don't"
                        cv2.putText(im0, txt, org, cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 1)

                        # # DeepSORT -> Saving Track predictions into a text file.

                        # with open(txt_path + '.txt', 'a') as f:
                        #     line = save_format.format(frame=frame_idx, id=track.track_id, x1=int(bbox[0]),
                        #                               y1=int(bbox[1]), w=int(bbox[2] - bbox[0]),
                        #                               h=int(bbox[3] - bbox[1]), x=-1, y=-1, z=-1)
                        #     f.write(line)
                    Widget.detect_change_system.newstart()
                    Widget.detectPeople.clearframe()

                    # 第三步重要的结果！！！
                    # Write results
                    for *xyxy, conf, cls in reversed(det):
                        if save_txt:  # Write to file
                            xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                            print(xywh)
                            cv2.circle(im0, (int(xywh[0]*im0.shape[:2][1]), int(xywh[1]*im0.shape[:2][0])), 10, (0, 0, 255), -1)

                            line = (cls, *xywh, conf) if save_conf else (cls, *xywh)  # label format




                            # with open(f'{txt_path}.txt', 'a') as f:
                            #     f.write(('%g ' * len(line)).rstrip() % line + '\n')

                        if save_img or save_crop or view_img:  # Add bbox to image
                            c = int(cls)  # integer class
                            label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
                            annotator.box_label(xyxy, label, color=colors(c, True))
                        if save_crop:
                            save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)
                ##########################################重要部分流处理############################################


                # im0 = annotator.result()

                if view_img:
                    if platform.system() == 'Linux' and p not in windows:
                        windows.append(p)
                        cv2.namedWindow(str(p), cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)  # allow window resize (Linux)
                        cv2.resizeWindow(str(p), im0.shape[1], im0.shape[0])

                    cv2.imshow(str(p), im0)
                    cv2.waitKey(1)  # 1 millisecond

                # Save results (image with detections)
                if save_img:
                    if dataset.mode == 'image':
                        cv2.imwrite(save_path, im0)
                    else:  # 'video' or 'stream'
                        if vid_path[i] != save_path:  # new video
                            vid_path[i] = save_path
                            if isinstance(vid_writer[i], cv2.VideoWriter):
                                vid_writer[i].release()  # release previous video writer
                            if vid_cap:  # video
                                fps = vid_cap.get(cv2.CAP_PROP_FPS)
                                w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                                h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                            else:  # stream
                                fps, w, h = 30, im0.shape[1], im0.shape[0]
                            save_path = str(Path(save_path).with_suffix('.mp4'))  # force *.mp4 suffix on results videos
                            vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
                        vid_writer[i].write(im0)
            # 将图像矩阵转换为QImage对象
            # 将opencv的BGR转化为RGB图像
            rgb_image = cv2.cvtColor(im0, cv2.COLOR_BGR2RGB)

            height, width, channels = rgb_image.shape
            bytes_per_line = channels * width
            qimage = QImage(rgb_image.data, width, height, bytes_per_line,QImage.Format_RGB888)
            # 将QImage对象转换为QPixmap对象
            qpixmap = QPixmap.fromImage(qimage)
            queue.put(qpixmap)
            # Print time (inference-only)
            LOGGER.info(f"{s}{'' if len(det) else '(no detections), '}{dt[1].dt * 1E3:.1f}ms")

        # Print results
        t = tuple(x.t / seen * 1E3 for x in dt)  # speeds per image
        LOGGER.info(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {(1, 3, *imgsz)}' % t)
        if save_txt or save_img:
            s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
            LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
        if update:
            strip_optimizer(weights[0])  # update model (to fix SourceChangeWarning)

    @staticmethod
    def parse_opt(source,Widget):
        """
        weights: 训练的权重路径,可以使用自己训练的权重,也可以使用官网提供的权重
        默认官网的权重yolov5s.pt(yolov5n.pt/yolov5s.pt/yolov5m.pt/yolov5l.pt/yolov5x.pt/区别在于网络的宽度和深度以此增加)
        source: 测试数据，可以是图片/视频路径，也可以是'0'(电脑自带摄像头),也可以是rtsp等视频流, 默认data/images
        data: 配置数据文件路径, 包括image/label/classes等信息, 训练自己的文件, 需要作相应更改, 可以不用管
        如果设置了只显示个别类别即使用了--classes = 0 或二者1, 2, 3等, 则需要设置该文件，数字和类别相对应才能只检测某一个类
        imgsz: 网络输入图片大小, 默认的大小是640
        conf-thres: 置信度阈值， 默认为0.25
        iou-thres:  做nms的iou阈值, 默认为0.45
        max-det: 保留的最大检测框数量, 每张图片中检测目标的个数最多为1000类
        device: 设置设备CPU/CUDA, 可以不用设置
        view-img: 是否展示预测之后的图片/视频, 默认False, --view-img 电脑界面出现图片或者视频检测结果
        save-txt: 是否将预测的框坐标以txt文件形式保存, 默认False, 使用--save-txt 在路径runs/detect/exp*/labels/*.txt下生成每张图片预测的txt文件
        save-conf: 是否将置信度conf也保存到txt中, 默认False
        save-crop: 是否保存裁剪预测框图片, 默认为False, 使用--save-crop 在runs/detect/exp*/crop/剪切类别文件夹/ 路径下会保存每个接下来的目标
        nosave: 不保存图片、视频, 要保存图片，不设置--nosave 在runs/detect/exp*/会出现预测的结果
        classes: 设置只保留某一部分类别, 形如0或者0 2 3, 使用--classes = n, 则在路径runs/detect/exp*/下保存的图片为n所对应的类别, 此时需要设置data
        agnostic-nms: 进行NMS去除不同类别之间的框, 默认False
        augment: TTA测试时增强/多尺度预测
        visualize: 是否可视化网络层输出特征
        update: 如果为True,则对所有模型进行strip_optimizer操作,去除pt文件中的优化器等信息,默认为False
        project:保存测试日志的文件夹路径
        name:保存测试日志文件夹的名字, 所以最终是保存在project/name中
        exist_ok: 是否重新创建日志文件, False时重新创建文件
        line-thickness: 画框的线条粗细
        hide-labels: 可视化时隐藏预测类别
        hide-conf: 可视化时隐藏置信度
        half: 是否使用F16精度推理, 半进度提高检测速度
        dnn: 用OpenCV DNN预测
        """
        parser = argparse.ArgumentParser()
        parser.add_argument('--weights', nargs='+', type=str, default='./yolov5n.pt',
                            help='model path or triton URL')
        parser.add_argument('--source', type=str, default=source,
                            help='file/dir/URL/glob/screen/0(webcam)')
        parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='(optional) dataset.yaml path')
        parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[Widget.label.pixmap().height(),Widget.label.pixmap().width() ],
                            help='inference size h,w')
        parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
        parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
        parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')
        parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
        parser.add_argument('--view-img', default=False,action='store_true', help='show results')
        parser.add_argument('--save-txt',default=False,action='store_true', help='save results to *.txt')
        parser.add_argument('--save-conf',default=False ,action='store_true', help='save confidences in --save-txt labels')
        parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
        parser.add_argument('--nosave', default=False,action='store_true', help='do not save images/videos')
        parser.add_argument('--classes', default=0,nargs='+', type=int, help='filter by class: --classes 0, or --classes 0 2 3')
        parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
        parser.add_argument('--augment', action='store_true', help='augmented inference')
        parser.add_argument('--visualize', action='store_true', help='visualize features')
        parser.add_argument('--update', action='store_true', help='update all models')
        parser.add_argument('--project', default=ROOT / 'runs/detect', help='save results to project/name')
        parser.add_argument('--name', default='exp', help='save results to project/name')
        parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
        parser.add_argument('--line-thickness', default=1, type=int, help='bounding box thickness (pixels)')
        parser.add_argument('--hide-labels', default=True, action='store_true', help='hide labels')
        parser.add_argument('--hide-conf', default=True, action='store_true', help='hide confidences')
        parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
        parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
        parser.add_argument('--vid-stride', type=int, default=1, help='video frame-rate stride')
        opt = parser.parse_args()
        opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1  # expand
        print_args(vars(opt))
        return opt

    def main(self,queue,source,Widget):
        opt = yolov5.parse_opt(source,Widget)
        check_requirements(exclude=('tensorboard', 'thop'))
        yolov5.run(queue,Widget,**vars(opt))